from bge import logic
import bpy
from bge import events
import Rasterizer
Rasterizer.showMouse(0)
from bge import render
import random
import bpy

#global vars
objectives = []
target = None

def GetRandomDirection():
    dir = logic.getRandomFloat()
    rand = logic.getRandomFloat()
    if dir > 0.5:
        return -rand
    else:
        return rand
    pointInsideMesh(object, mathutils.Vector((90,3,-10)), mathutils.Vector((1,0,0)))

def GenerateObjectives():
    global objectives
    dim = GetFloorDimension()
    loc = GetFloorLocation()
    scene = logic.getCurrentScene()
    
    City = bpy.context.scene.CityName
    
    
    for i in range(40):
        objective = scene.addObject("Objective", City) 
        objective.position = (-dim[0]/2 + (logic.getRandomFloat()*dim[0]), -dim[1]/2 + (logic.getRandomFloat()*dim[1]), 0)
        #print(objective.position)
        objectives.append(objective)
        

def ChangeObjective():
    global objectives
    controller = logic.getCurrentController()
    act = controller.actuators["Steering_ACT"]
    if act.target and 'human' in act.target:
        return
        
    if not objectives:
        GenerateObjectives()
    SwitchTarget(random.choice(objectives))

def CheckForFood():
    controller = logic.getCurrentController()
    act = controller.actuators["Steering_ACT"]
    if not act.target:
        ChangeObjective()

def CheckDestination():
    global target
    controller = logic.getCurrentController()
    sen = controller.sensors["Check Destination_SEN"]
    act = controller.actuators["Steering_ACT"]
    
    if act.target and 'human' in act.target:
        return
    
    if 'Panic' in controller.owner:
        controller.owner["Panic"] -= 10
        if controller.owner["Panic"] <= 0:
            act.velocity = 1
            arm = controller.owner.children
            actAnim = arm[0].actuators["Action_ACT"]
            actAnim.action = "Walk"
            actAnim.frameEnd = 40
            ChangeObjective()
            
    for closeObject in sen.hitObjectList:
        if closeObject == act.target:
            ChangeObjective()

fleeObjectives = []

def CleanObjectives():
    global fleeObjectives
    j = 0
    for i in fleeObjectives:
        i.endObject()
        del fleeObjectives[0]
        j = j+1
        if fleeObjectives.length <= bpy.types.Scene.NbHuman:
            return

def FleeZombie():
    controller = logic.getCurrentController()
    sen = controller.sensors["Flee Zombie_SEN"]
    
    if not sen.hitObjectList:
        return
    
    act = controller.actuators["Steering_ACT"]
    act.velocity = controller.owner['Velocity']

    controller.owner["Panic"] = 100
    direction = controller.owner.position - sen.hitObjectList[0].position
    direction.normalize()
    objective = logic.getCurrentScene().addObject("Objective", bpy.context.scene.CityName) 
    objective.position = controller.owner.position + direction * 100
    act.target = objective
    
    global fleeObjectives
    fleeObjectives.append(objective)
    
    if controller.owner["Infected"]:
        return
    
    arm = controller.owner.children
    actAnim = arm[0].actuators["Action_ACT"]
    actAnim.action = "Run"
    actAnim.frameEnd = 20

def CreateObject(type, markId):
    
    Human = bpy.context.scene.HumanName
    Zombie = bpy.context.scene.ZombieName
    
    scene = logic.getCurrentScene()
    if type == "human":
        markString = "Pop_Human_Mark_" + str(markId)
        hum = scene.addObject(Human, markString)
        rand = logic.getRandomFloat() * 2 + 2
        hum['Velocity'] = rand
    elif type == "zombie" :
        markString = "Pop_Zombie_Mark_" + str(markId)
        zomb = scene.addObject(Zombie, markString)
    
    #hum.position.z = 2
    #hum.position.x = loc[0] + GetRandomDirection() * dim[0]/2
    #hum.position.y = loc[1] + GetRandomDirection() * dim[1]/2
    
def RandomFillMarks(marks, nbHumans):
    size = len(marks)
    while (nbHumans != 0):
        rand = random.randint(0,size-1)
        marks[rand] = marks[rand] + 1
        nbHumans = nbHumans - 1
    return marks
        
    
def GeneratePopulation(nbHumans, type, nbMarks):
    marks = []
    
    for m in range(nbMarks):
        marks.append(0)
    
    marks = RandomFillMarks(marks, nbHumans)
    
    for i in range(nbMarks):
        for j in range(marks[i]):
            CreateObject(type, i)
        
def GetFloorDimension():
    City = bpy.context.scene.CityName
    return bpy.data.objects[City].dimensions

def GetFloorLocation():
    City = bpy.context.scene.CityName
    return bpy.data.objects[City].location


def pointInsideMesh(object, point, axis):
    outside = False
    axes = [ axis, -axis ]
    for axis in axes:
        mat = mathutils.Matrix(object.matrix_world)
        orig = mat.inverted() * point
        count = 0
        while True:
            location,normal,index = object.ray_cast(orig, orig + axis * 10000.0)
            if index == -1:
                break
            count += 1
            orig = location + axis * 0.00001
        if count % 2 == 0:
            outside = True
    return not outside

def CheckNavMesh():
    
    scene = logic.getCurrentScene()
    
    controller = logic.getCurrentController()
    act = controller.actuators["Steering_ACT"]
    
    if act.navmesh == None:
        act.navmesh = scene.objects["Navmesh"]

def InitMouse():
    render.setMousePosition(int(render.getWindowWidth() / 2),int(render.getWindowHeight() / 2))

    
def GetClosestObject():
    global target
    
    controller = logic.getCurrentController()
    
    sen = controller.sensors["Get Closest Object_SEN"]
    
    if(len(sen.hitObjectList) > 0):
        closestDistance = 0
        closestObject = None
        if sen.hitObjectList[0]["Infected"] == False:
            closestObject = sen.hitObjectList[0]
            closestDistance = closestObject.getDistanceTo(controller.owner)
        for hitObject in sen.hitObjectList:
            distance = hitObject.getDistanceTo(controller.owner)
            if distance < closestDistance and hitObject["Infected"] == False:
                closestObject = hitObject
                closestDistance = distance
        
        if(closestObject != target):
            target = closestObject
            SwitchTarget(target)
            
def SwitchTarget(newTarget):
    scene = logic.getCurrentScene()
    controller = logic.getCurrentController()
    act = controller.actuators["Steering_ACT"]
    act.target = newTarget

def GetInfected():
    scene = logic.getCurrentScene()
    controller = logic.getCurrentController()
    act = controller.actuators["Steering_ACT"]
    act.velocity = 0
    obj = controller.owner
   
    arm = controller.owner.children
    actAnim = arm[0].actuators["Action_ACT"]
    actAnim.action = "Idle"
    
    obj = controller.owner
    if 'Infected' in obj:
        obj['Infected'] = True        
       
def HumanTransformation():  
    scene = logic.getCurrentScene()
    controller = logic.getCurrentController()
    obj = controller.owner
    
    if (obj['Infected']):  
        Zombie = bpy.context.scene.ZombieName        
        zomb = scene.addObject(Zombie, "Pop_Zombie_Mark_0")
        zomb.position = obj.position 
        obj.endObject()
        
def LaunchBomb():
    controller = logic.getCurrentController()    
    sen = controller.sensors["Launch Bomb_SEN"]
    if not sen.positive:
        return
    scene = logic.getCurrentScene()
    Bomb = bpy.context.scene.objects["Bomb"]
    bomb = scene.addObject("Bomb", "Pop_Bomb_Mark")
    pos = controller.owner.position
    bomb.position = (pos[0],pos[1],pos[2]-5)
    
def DestroyBomb():
    controller = logic.getCurrentController()
    obj = controller.owner
    obj.endObject()
 